﻿#include "processmodule.h"
LdrLoadDllDef LdrLoadDll64;

ProcessService::ProcessService()
{
    HMODULE hNtdll = GetModuleHandleA("ntdll.dll");

    IsWow64Process =  (IsWow64ProcessDef)::GetProcAddress(GetModuleHandleA("Kernel32.dll"),"IsWow64Process");

    //查询线程详细信息
    NtQueryInformationThread =  (NtQueryInformationThreadDef)::GetProcAddress(hNtdll,"ZwQueryInformationThread");
    //查询进程列表,以及线程状态等信息
    NtQuerySystemInformation =  (NtQuerySystemInformationDef)::GetProcAddress(hNtdll,"NtQuerySystemInformation");
    //挂起进程
    NtSuspendProcess =          (NtSuspendProcessDef)::GetProcAddress(hNtdll,"NtSuspendProcess");
    //恢复进程
    NtResumeProcess =           (NtResumeProcessDef)::GetProcAddress(hNtdll,"NtResumeProcess");

    NtQueryVirtualMemory = (NtQueryVirtualMemoryDef)::GetProcAddress(hNtdll,"NtQueryVirtualMemory"); //NtQueryVirtualMemory

    LdrLoadDll64 =  (LdrLoadDllDef)::GetProcAddress(hNtdll,"LdrLoadDll"); //LdrLoadDll


}




//创建进程列表快照
bool ProcessService::CreateProcessListSnapshot(QList<ProcessBean>* qProcessList)
{
    qProcessList->clear();
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    if (INVALID_HANDLE_VALUE == hSnapshot)
    {
        return false;
    }
    PROCESSENTRY32 pi;
    pi.dwSize = sizeof(PROCESSENTRY32); //第一次使用必须初始化成员
    BOOL bRet = Process32First(hSnapshot,&pi);
    while (bRet)
    {
        TCHAR modulePath[MAX_PATH];
        WINBOOL isGetOk =  this->GetProcessFullPath(pi.th32ProcessID,modulePath);
        ProcessBean processListBean;
        processListBean.pId=pi.th32ProcessID;
        processListBean.threadCount=pi.cntThreads;
        processListBean.parentPId=pi.th32ParentProcessID;
        processListBean.pName=QString::fromWCharArray(pi.szExeFile);
        processListBean.pPath=isGetOk?QString::fromWCharArray(modulePath):QString();
        processListBean.companyName = fileService.GetFileInformation(processListBean.pPath,CompanyName);
        HANDLE hprocess = OpenProcess(PROCESS_ALL_ACCESS,false,processListBean.pId);
        processListBean.bit = 0;
        if (hprocess) {
            BOOL isWow64;
            //进程位数
            if (this->IsWow64Process(hprocess,&isWow64))
            {
                processListBean.bit = isWow64?Mode32:Mode64;
            }
            SafeCloseHandle(hprocess);
        }

        if (processListBean.companyName.isEmpty())
        {
            //            qDebug()<<" Get companyName: No Company Information:"<<processListBean.pPath;
            processListBean.companyName = fileService.GetFileInformation(processListBean.pPath,LegalCopyright);
        }
        //如果是空闲进程和系统进程,特殊设置路径值
        if (processListBean.pId==IDLE_PROCESS_ID)
        {
            processListBean.pPath=QString("System Idle Process");
        }
        if (processListBean.pId==SYSTEM_PROCESS_ID)
        {
            processListBean.pPath=QString("System");
        }
        qProcessList->append(processListBean);
        bRet = Process32Next(hSnapshot,&pi);
    }
    return true;
}



BOOL ProcessService::DosPathToNtPath(LPTSTR pszDosPath, LPTSTR pszNtPath)
{
    TCHAR            szDriveStr[500];
    TCHAR            szDrive[3];
    TCHAR            szDevName[100];
    INT                cchDevName;
    INT                i;

    //检查参数
    if(!pszDosPath || !pszNtPath )
        return FALSE;

    //获取本地磁盘字符串
    if(GetLogicalDriveStrings(sizeof(szDriveStr), szDriveStr))
    {
        for(i = 0; szDriveStr[i]; i += 4)
        {
            if(!lstrcmpi(&(szDriveStr[i]), TEXT("A:\\")) || !lstrcmpi(&(szDriveStr[i]), TEXT("B:\\")))
                continue;

            szDrive[0] = szDriveStr[i];
            szDrive[1] = szDriveStr[i + 1];
            szDrive[2] = '\0';
            if(!QueryDosDevice(szDrive, szDevName, 100))//查询 Dos 设备名
                return FALSE;

            cchDevName = lstrlen(szDevName);
            if(_tcsnicmp(pszDosPath, szDevName, cchDevName) == 0)//命中
            {
                lstrcpy(pszNtPath, szDrive);//复制驱动器
                lstrcat(pszNtPath, pszDosPath + cchDevName);//复制路径
                return TRUE;
            }
        }
    }

    lstrcpy(pszNtPath, pszDosPath);

    return FALSE;
}

//获取进程完整路径
BOOL ProcessService::GetProcessFullPath(DWORD dwPID, TCHAR pszFullPath[MAX_PATH])
{
    TCHAR        szImagePath[MAX_PATH];
    HANDLE        hProcess;
    if(!pszFullPath)
        return FALSE;

    pszFullPath[0] = '\0';
    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, dwPID);
    if(!hProcess)
        return FALSE;

    if(!GetProcessImageFileName(hProcess, szImagePath, MAX_PATH))
    {
        SafeCloseHandle(hProcess);
        return FALSE;
    }

    if(!DosPathToNtPath(szImagePath, pszFullPath))
    {
        SafeCloseHandle(hProcess);
        return FALSE;
    }
    SafeCloseHandle(hProcess);
    return TRUE;
}

BOOLEAN NtPathToDosPathW(WCHAR* FullNtPath, WCHAR* FullDosPath)
{
    WCHAR DosDevice[4] = { 0 };       //dos设备名最大长度为4
    WCHAR NtPath[64] = { 0 };       //nt设备名最大长度为64
    size_t NtPathLen = 0;
    short i = 0;
    if (!FullNtPath || !FullDosPath)
    {
        return FALSE;
    }
    for (i = 65; i < 26 + 65; i++)
    {
        DosDevice[0] = i;
        DosDevice[1] = L':';
        if (QueryDosDeviceW(DosDevice, NtPath, 64))
        {
            if (NtPath)
            {
                NtPathLen = wcslen(NtPath);
                if (!_wcsnicmp(NtPath, FullNtPath, NtPathLen))
                {
                    wcscpy(FullDosPath, DosDevice);
                    wcscat(FullDosPath, FullNtPath + NtPathLen);
                    return TRUE;
                }
            }
        }
    }
    return FALSE;
}
//获取令牌权限
BOOL ProcessService::EnableDebugPrivilege()
{
    HANDLE hToken;
    BOOL fOk=FALSE;
    if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken)) //Get Token
    {
        TOKEN_PRIVILEGES tp;
        tp.PrivilegeCount=1;
        if(!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid))//Get Luid
            qDebug()<<("Can't lookup privilege value.\n");
        tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;//这一句很关键，修改其属性为SE_PRIVILEGE_ENABLED
        if(!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL))//Adjust Token
            qDebug()<<("Can't adjust privilege value.\n");
        fOk=(GetLastError()==ERROR_SUCCESS);
        CloseHandle(hToken);
    }
    return fOk;
}

bool ProcessService::GetProcessThreadList(DWORD dwPID,QList<ProcessThreadBean>*qProcessThreadList)
{
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,false,dwPID);
    if (!hProcess) {
        qDebug()<<"OpenProcess fail!";
        return false;
    }
    HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
    THREADENTRY32 threadEntry;
    RtlZeroMemory(&threadEntry,sizeof(THREADENTRY32));
    threadEntry.dwSize = sizeof( THREADENTRY32 );
    // 创建一个快照句柄
    hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwPID);
    if (hThreadSnap == INVALID_HANDLE_VALUE)
    {
        qDebug()<<"INVALID_HANDLE_VALUE! LastError:"<<GetLastError();
        return false;
    }
    // 通过模块快照句柄获取第一个模块
    if (!Thread32First(hThreadSnap, &threadEntry))
    {
        qDebug()<<"Thread32First fail! LastError:"<<GetLastError();
        SafeCloseHandle(hThreadSnap);
        return false;
    }

    do {
        if (threadEntry.th32OwnerProcessID==dwPID)
        {
            //封装模块信息
            ProcessThreadBean processThreadListBean;
            RtlZeroMemory(&processThreadListBean,sizeof(ProcessThreadBean));
            //线程优先级
            processThreadListBean.Priority = threadEntry.tpBasePri;
            //线程id
            processThreadListBean.threadId = threadEntry.th32ThreadID;
            //引用计数
            processThreadListBean.cntUsage = threadEntry.cntUsage;
            ULONG_PTR dwStaAddr;
            HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, threadEntry.th32ThreadID);
            NTSTATUS ntstatus =  NtQueryInformationThread(hThread, ThreadQuerySetWin32StartAddress,
                                                          &dwStaAddr, sizeof(dwStaAddr), NULL);
            if (ntstatus==STATUS_SUCCESS) {
                processThreadListBean.threadEntryPoint = dwStaAddr;
            }
            // 获取线程所在模块
            THREAD_BASIC_INFORMATION tbi;			// _THREAD_BASIC_INFORMATION 结构体对象
            TCHAR modname[MAX_PATH];				// 用来接收模块全路径
            ntstatus =  NtQueryInformationThread(
                        hThread,							// 线程句柄
                        ThreadBasicInformation,				// 线程信息类型，ThreadBasicInformation ：线程基本信息
                        &tbi,								// 指向缓冲区的指针
                        sizeof(tbi),						// 缓冲区的大小
                        NULL
                        );
            SafeCloseHandle(hThread);
            if (ntstatus==STATUS_SUCCESS)
            {
                //线程优先级,teb,状态
                processThreadListBean.Priority = tbi.BasePriority;
                processThreadListBean.teb = (ULONG64)tbi.TebBaseAddress;
                processThreadListBean.status = tbi.ExitStatus;

                SYSTEM_THREAD_INFORMATION sti;
                bool getOk =    this->GetThreadStatusInfo(dwPID, threadEntry.th32ThreadID,&sti);
                if (getOk) {
                    processThreadListBean.status = sti.ThreadState;
                    processThreadListBean.waitReason = sti.WaitReason;
                }else {
                    qDebug()<<"GetThreadStatusInfo false!";
                }
                // 检查入口地址是否位于某模块中
                if (GetMappedFileName(hProcess,(PVOID64)dwStaAddr,modname,MAX_PATH))
                {
                    NtPathToDosPathW(modname,processThreadListBean.moudleName);
                }
            }else {
                qDebug()<<"NtQueryInformationThread false! ntstatus:"<<ntstatus;
            }
            qProcessThreadList->append(processThreadListBean);
        }

    } while (Thread32Next(hThreadSnap,&threadEntry));

    // 关闭句柄并且退出函数
    CloseHandle(hThreadSnap);
    SafeCloseHandle(hProcess);
    return true;
}


bool ProcessService::CreateProcessModuleListSnapshot(DWORD dwPID ,QList<ProcessModuleBean>*qProcessModuleList)
{
    HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
    MODULEENTRY32 moudleEntry;
    RtlZeroMemory(&moudleEntry,sizeof(MODULEENTRY32));
    moudleEntry.dwSize = sizeof( MODULEENTRY32 );
    // 创建一个快照句柄
    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE|TH32CS_SNAPMODULE32, dwPID);
    if (hModuleSnap == INVALID_HANDLE_VALUE)
    {
        qDebug()<<"INVALID_HANDLE_VALUE!"<<GetLastError();
        return false;
    }
    // 通过模块快照句柄获取第一个模块
    if (!Module32First(hModuleSnap, &moudleEntry))
    {
        qDebug()<<"Module32First fail!"<<GetLastError();
        CloseHandle(hModuleSnap);
        return false;
    }

    do {
        //封装模块信息
        ProcessModuleBean processModuleListBean;
        //模块路径
        processModuleListBean.modulePath = QString::fromWCharArray(moudleEntry.szExePath);
        //模块基址
        processModuleListBean.moduleAddress =(ULONG_PTR)moudleEntry.modBaseAddr;
        //模块大小
        processModuleListBean.moduleSize = moudleEntry.modBaseSize;
        //公司信息
        processModuleListBean.companyName=fileService.GetFileInformation(processModuleListBean.modulePath,CompanyName);

        ULONG entryPoint=0;
        if (fileService.GetFileEntryPoint(moudleEntry.szExePath,&entryPoint))
        {
            //模块入口
            processModuleListBean.moduleEntryPoint = entryPoint + processModuleListBean.moduleAddress;
        }

        qProcessModuleList->append(processModuleListBean);
    } while (Module32Next(hModuleSnap, &moudleEntry));

    // 关闭句柄并且退出函数
    CloseHandle(hModuleSnap);
    return true;
}
//创建进程列表快照
bool ProcessService::GetSpecifiedModuleInformation(ULONG dwPId, PProcessModuleBean module)
{

    QList<ProcessModuleBean>qProcessModuleList;
    //创建模块快照,进行比对
    bool createOk =  this->CreateProcessModuleListSnapshot(dwPId,&qProcessModuleList);
    if (createOk && !qProcessModuleList.isEmpty())
    {
        for (int objectIndex = 0; objectIndex < qProcessModuleList.size(); ++objectIndex)
        {
            //按下标获取模块信息
            ProcessModuleBean processModuleBean =  qProcessModuleList.at(objectIndex);

            if (!QString::compare(processModuleBean.modulePath,module->modulePath,Qt::CaseInsensitive))
            {
                module->companyName = processModuleBean.companyName;
                module->moduleAddress = processModuleBean.moduleAddress;
                module->moduleEntryPoint = processModuleBean.moduleEntryPoint;
                module->moduleSize = processModuleBean.moduleSize;
                return TRUE;
            }

        }
    }
    return FALSE;
}

//获取线程状态
bool ProcessService::GetThreadStatusInfo(ULONG dwPId,ULONG dwTId,PSYSTEM_THREAD_INFORMATION psti)
{
    PSYSTEM_PROCESS_INFORMATION spi=NULL,spiIterator;
    ULONG dwRtnLength=0;
    //查询进程和线程列表所需内存空间大小
    NTSTATUS ntstatus = NtQuerySystemInformation(SystemProcessInformation,NULL,0,&dwRtnLength);

    if (STATUS_INFO_LENGTH_MISMATCH==ntstatus && dwRtnLength)
    {
        dwRtnLength+=0x1000;
        spiIterator= spi = (PSYSTEM_PROCESS_INFORMATION)malloc(dwRtnLength);
        RtlZeroMemory(spiIterator,dwRtnLength);
        ntstatus = NtQuerySystemInformation(SystemProcessInformation,spiIterator,dwRtnLength,&dwRtnLength);
        if (ntstatus!=STATUS_SUCCESS) {
            qDebug()<<"NtQuerySystemInformation Fail! ErrorCode:"<<GetLastError();
            goto QueryFail;
        }
        while(TRUE)
        {
            if ((ULONG_PTR)spiIterator->UniqueProcessId == dwPId)
            {
                //遍历进程列表和线程列表.查找匹配的线程id,获取线程状态
                for (ULONG threadIndex = 0; threadIndex < spiIterator->NumberOfThreads; ++threadIndex)
                {
                    SYSTEM_THREAD_INFORMATION threads = spiIterator->Threads[threadIndex];
                    if ((ULONG_PTR)(threads.ClientId.UniqueThread)==dwTId) {
                        *psti = threads;
                        SafeFree(spi);
                        return true;
                    }
                }
            }
            if (!spiIterator->NextEntryOffset) {
                break;
            }
            spiIterator = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)spiIterator + spiIterator->NextEntryOffset);
        }
    }
QueryFail:
    SafeFree(spi);
    return false;
}



QString ProcessService::GetThreadStateString(THREAD_STATE threadStatus, KWAIT_REASON waitReason)
{
    QString rtnString;
    switch (threadStatus) {
    case StateInitialized:
        rtnString = "初始化";
        break;
    case StateReady        :
        rtnString = "就绪";
        break;
    case StateRunning      :
        rtnString = "运行中";
        break;
    case StateStandby      :
        rtnString = "停滞";
        break;
    case StateTerminated   :
        rtnString = "已终止";
        break;
    case StateWait         :
        rtnString = "等待";
        switch (waitReason)
        {
        case  Executive:          rtnString.append("(Executive)");          break;
        case  FreePage:           rtnString.append("(FreePage)");           break;
        case  PageIn:             rtnString.append("(PageIn)");             break;
        case  PoolAllocation:     rtnString.append("(PoolAllocation)");     break;
        case  DelayExecution:     rtnString.append("(DelayExecution)");     break;
        case  Suspended:          rtnString.append("(Suspended)");          break;
        case  UserRequest:        rtnString.append("(UserRequest)");        break;
        case  WrExecutive:        rtnString.append("(WrExecutive)");        break;
        case  WrFreePage:         rtnString.append("(WrFreePage)");         break;
        case  WrPageIn:           rtnString.append("(WrPageIn)");           break;
        case  WrPoolAllocation:   rtnString.append("(WrPoolAllocation)");   break;
        case  WrDelayExecution:   rtnString.append("(WrDelayExecution)");   break;
        case  WrSuspended:        rtnString.append("(WrSuspended)");        break;
        case  WrUserRequest:      rtnString.append("(WrUserRequest)");      break;
        case  WrSpare0:           rtnString.append("(WrSpare0)");           break;
        case  WrQueue:            rtnString.append("(WrQueue)");            break;
        case  WrLpcReceive:       rtnString.append("(WrLpcReceive)");       break;
        case  WrLpcReply:         rtnString.append("(WrLpcReply)");         break;
        case  WrVirtualMemory:    rtnString.append("(WrVirtualMemory)");    break;
        case  WrPageOut:          rtnString.append("(WrPageOut)");          break;
        case  WrRendezvous:       rtnString.append("(WrRendezvous)");       break;
        case  WrKeyedEvent:       rtnString.append("(WrKeyedEvent)");       break;
        case  WrTerminated:       rtnString.append("(WrTerminated)");       break;
        case  WrProcessInSwap:    rtnString.append("(WrProcessInSwap)");    break;
        case  WrCpuRateControl:   rtnString.append("(WrCpuRateControl)");   break;
        case  WrCalloutStack:     rtnString.append("(WrCalloutStack)");     break;
        case  WrKernel:           rtnString.append("(WrKernel)");           break;
        case  WrResource:		  rtnString.append("(WrResource)");         break;
        case  WrPushLock:         rtnString.append("(WrPushLock)");         break;
        case  WrMutex:            rtnString.append("(WrMutex)");            break;
        case  WrQuantumEnd:       rtnString.append("(WrQuantumEnd)");       break;
        case  WrDispatchInt:      rtnString.append("(WrDispatchInt)");      break;
        case  WrPreempted:        rtnString.append("(WrPreempted)");        break;
        case  WrYieldExecution:   rtnString.append("(WrYieldExecution)");   break;
        case  WrFastMutex:        rtnString.append("(WrFastMutex)");        break;
        case  WrGuardedMutex:     rtnString.append("(WrGuardedMutex)");     break;
        case  WrRundown:          rtnString.append("(WrRundown)");          break;
        case  WrAlertByThreadId:  rtnString.append("(WrAlertByThreadId)");  break;
        case  WrDeferredPreempt:  rtnString.append("(WrDeferredPreempt)");  break;
        case  WrPhysicalFault:    rtnString.append("(WrPhysicalFault)");    break;
        case  MaximumWaitReason:  rtnString.append("(MaximumWaitReason)");  break;
        default:
            break;
        }
        break;
    case StateTransition   :
        rtnString = "StateTransition";
        break;
    case StateUnknown:
        rtnString = "未知";
        break;
    default:
        rtnString = "未知";
        break;
    }

    return rtnString;
}

QPixmap ProcessService::GetFileIcon(QString path)
{
    QFileInfo fileInfo(path);
    QFileIconProvider icon;
    QPixmap pixmap = icon.icon(fileInfo).pixmap(32,32);
    //    pixmap.save(savePath);
    return pixmap;
}

//恢复进程
ULONG ProcessService::NtResumeProcessImpl(HANDLE hProcess)
{
    NTSTATUS ntstatus =  NtResumeProcess(hProcess);
    if (STATUS_SUCCESS!=ntstatus)
    {
        //挂起失败,采用APC方式挂起
        qDebug()<<"恢复进程失败";
    }
    return ntstatus;
}




//挂起进程
ULONG ProcessService::NtSuspendProcessImpl(HANDLE hProcess)
{
    NTSTATUS ntstatus =  NtSuspendProcess(hProcess);
    if (STATUS_SUCCESS!=ntstatus) {
        //挂起失败,采用驱动APC方式挂起
    }
    return ntstatus;
}

//结束进程
bool ProcessService::NtTerminateProcessImpl(ULONG dwPId,UINT uExitCode)
{
    HANDLE hProcess =  OpenProcess(PROCESS_ALL_ACCESS,false,dwPId);
    WINBOOL terminateOk =  TerminateProcess(hProcess,uExitCode);
    if (!terminateOk)
    {
        qDebug()<<"TerminateProcess : " << terminateOk;
        //结束进程失败,采用驱动方式结束
    }
    SafeCloseHandle(hProcess);
    return terminateOk;
}


VOID FnLoadDllShellCode(_In_ ULONG_PTR dwData)
{
    PInjectData pInjectData = (PInjectData)dwData;
    pInjectData->LdrLoadDll64(NULL,0,&pInjectData->ModuleFileName,&pInjectData->ModuleHandle);
    pInjectData->TerminateThread((HANDLE)-2,0);
}



//注入dll到指定进程空间
bool ProcessService::InjectDllToProcess(ULONG dwPId,QString szExePath)
{

    HANDLE hProcess =  OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwPId);
    //打开进程句柄成功
    if (hProcess)
    {
        InjectType InjectTy=PROCESS32_DLL32;
        BOOL isWow64=false;
        //DLL路径
        std::wstring wstr = szExePath.toStdWString();
        //获取dll运行平台
        DisassembleMode model =  fileService.GetFilePlatFormMachine(wstr.c_str());
        //构建注入类型
        if (IsWow64Process(hProcess,&isWow64))
        {
            //如果函数执行成功
            if (isWow64)
            {
                //目标进程为32位进程
                if (model==Mode32)
                {
                    InjectTy = PROCESS32_DLL32;
                    goto PROCESS32_DLL32_LABEL;
                }else {
                    InjectTy = PROCESS32_DLL64;
                }
            }else{
                //目标进程为64位进程
                if (model==Mode32)
                {
                    InjectTy = PROCESS64_DLL32;
                    goto LabelUnsuccessful;
                }else {
                    InjectTy = PROCESS64_DLL64;
                    goto PROCESS32_DLL32_LABEL;
                }
            }
        }
        if (InjectTy == PROCESS32_DLL64)
        {
            //目标进程PAGE_SIZE数据结构划分
            /**
         * InjectData
         *                                  : PWCHAR PathToFile;
         *                                  : ULONG Flags;
         *                                  : HANDLE ModuleHandle;
         *                                  : LdrLoadDllDef LdrLoadDll32;
         *                                  : LdrLoadDllDef LdrLoadDll64;
         *                                  : TerminateThreadDef TerminateThread;
         *                                  : GetCurrentThreadDef GetCurrentThread;
         *                                  : UNICODE_STRING ModuleFileName;
         * DLL_PATH                         : 长度MAX_PATH
         * systemService.FnLoadDllShellCode : systemService.ShellCodeLength
         */
            //在目标进程申请PAGE_SIZE大小的内存用于存放ShellCode
            LPVOID allocBase =  VirtualAllocEx(hProcess,NULL,PAGE_SIZE,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
            //在当前进程申请同样大小的缓冲区并初始化,用于临时存放数据,然后拷贝到目标进程
            PInjectData pInjectData = (PInjectData)malloc(PAGE_SIZE);
            RtlZeroMemory(pInjectData,PAGE_SIZE);

            //拷贝DLL路径到缓冲区,拷贝位置于 InjectData 结构体大小之后
            RtlCopyMemory((PVOID)(&pInjectData->szDllPath),wstr.c_str(),wcslen(wstr.c_str())*2);
            //初始化存放DLL路径的Unicode结构体长度属性
            systemService.RtlInitUnicodeString(&pInjectData->ModuleFileName,wstr.c_str());
            ULONG_PTR offset = GetFieldOffset(InjectData,szDllPath);
            //此处DLL地址要计算处数据写入目标进程后的地址
            pInjectData->ModuleFileName.Buffer=(PWSTR)((ULONG_PTR)allocBase + offset);
            pInjectData->LdrLoadDll64 = SystemService::LdrLoadDll64;
            pInjectData->TerminateThread  = SystemService::NtTerminateThread;
            pInjectData->Flags = model;
            //共写入目标进程0x1000字节大小的内存,InjectData结构体用于存放数据,然后跟随ShellCode函数
            //shellCode函数写入目标进程的偏移量
            PVOID shellCodeOffset = (PVOID)((ULONG64)allocBase + sizeof(InjectData));
            RtlFillMemory(&pInjectData->threadParam,8,0x90);
            pInjectData->threadParam[0]=0xb9;
            *(PULONG)(&pInjectData->threadParam[1])=(ULONG)((ULONG_PTR)allocBase);

            pInjectData->switchX32ToX64[0]=0xea;
            *(PULONG)(&pInjectData->switchX32ToX64[1])=(ULONG)((ULONG_PTR)shellCodeOffset);
            pInjectData->switchX32ToX64[5]=0x33;
            pInjectData->switchX32ToX64[6]=0x0;


            //将所需的参数写入目标进程
            SIZE_T writeSize=0;
            WINBOOL writeOk =  WriteProcessMemory(hProcess,allocBase,pInjectData,PAGE_SIZE,&writeSize);
            //释放当前进程缓冲区
            SafeFree(pInjectData);
            if (writeOk && writeSize==PAGE_SIZE)
            {

                //拷贝ShellCode函数到目标进程shellCodeOffset处
                writeOk =  WriteProcessMemory(
                            hProcess                                 //目标进程句柄
                            ,shellCodeOffset                         //写入到目标进程指定内存Buffer处
                            ,(LPCVOID)&FnLoadDllShellCode            //写入源为ShellCode函数
                            ,SystemService::ShellCodeLength           //写入长度
                            ,&writeSize                              //返回实际写入长度
                            );
                if (writeOk && writeSize==SystemService::ShellCodeLength)
                {
                    PVOID threadEntry=shellCodeOffset;
                    if (InjectTy==PROCESS32_DLL64)
                    {
                        ULONG_PTR soffset = GetFieldOffset(InjectData,threadParam);
                        threadEntry = (PVOID) ((ULONG64)allocBase +  soffset);
                    }
                    qDebug()<<SystemService::GetFormatULONG64((ULONG64)threadEntry);

                    //启动远程线程,入口点即是FnLoadDllShellCode(已拷贝到 shellCodeOffset处)
                    HANDLE hThread = CreateRemoteThread(
                                hProcess
                                ,NULL
                                ,0
                                ,(LPTHREAD_START_ROUTINE)threadEntry
                                ,allocBase
                                ,0
                                ,NULL);
                    if (hThread)
                    {
                        qDebug()<<"LdrLoadDll 远程线程已创建!";
                        //等待远程线程自我销毁,3秒钟未收到响应则继续执行
                        WaitForSingleObject(hThread,3000);
                        SafeCloseHandle(hThread);
                        SafeCloseHandle(hProcess);
                        //释放目标进程内存
                        VirtualFreeEx(hProcess,allocBase,0,MEM_RELEASE);
                        qDebug()<<"LdrLoadDll 远程线程执行完成!";
                        return true;
                    }else {
                        qDebug()<<"LdrLoadDll 远程线程创建失败!";
                    }
                }else {
                    qDebug()<<"Error: writeOk:"<<writeOk<<"writeSize:"<<writeSize;
                }
            }
            goto LabelUnsuccessful;
        }

PROCESS32_DLL32_LABEL:
        std::string str = szExePath.toStdString();
        //创建远程线程注入
        PVOID VirBase =  VirtualAllocEx(hProcess,NULL,PAGE_SIZE,MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE);
        if (VirBase)
        {
            ULONG fileLength = strlen(str.c_str()) ;
            SIZE_T writeSize=0;
            WINBOOL writeOk =  WriteProcessMemory(hProcess,VirBase,str.c_str(),fileLength,&writeSize);
            if (writeOk && writeSize==fileLength)
            {
                ULONG_PTR threadAddress=0;
                if (InjectTy==PROCESS32_DLL32)
                {
                    threadAddress = SystemService::LoadLibraryA32;
                }
                if (InjectTy==PROCESS64_DLL64)
                {
                    threadAddress = SystemService::LoadLibraryA64;
                }
                HANDLE hThread = CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)threadAddress,VirBase,0,NULL);
                if (!hThread)
                {
                    qDebug()<<"CreateRemoteThread Fail！LastError:"<<GetLastError();
                    systemService.NtCreateThreadEx(
                                &hThread
                                ,0x1FFFFF
                                ,NULL
                                ,hProcess
                                ,(PVOID)threadAddress
                                ,VirBase
                                ,FALSE
                                ,0
                                ,0
                                ,0
                                ,NULL);
                   if (!hThread)
                    qDebug()<<"NtCreateThreadEx Fail！LastError:"<<GetLastError();
                }
                if (hThread)
                {
                    qDebug()<<"LoadLibrary 远程线程已创建!";
                    //等待远程线程自我销毁,3秒钟未收到响应则继续执行
                    WaitForSingleObject(hThread,3000);
//                    SystemService::NtTerminateThread(hThread,0);
                    SafeCloseHandle(hThread);
                    SafeCloseHandle(hProcess);
                    //释放目标进程内存
                    VirtualFreeEx(hProcess,VirBase,0,MEM_RELEASE);
                    qDebug()<<"LoadLibrary 远程线程执行完成!";
                    return true;
                }

            }
        }
    }else{
        qDebug()<<"InjectDll Fail！无法打开进程句柄!";
    }

LabelUnsuccessful:
    qDebug()<<"InjectDll Fail！";
    SafeCloseHandle(hProcess);
    return false;
}





//结束线程
NTSTATUS ProcessService::NtTerminateThreadImpl(ULONG threadId,UINT dwExitCode)
{
    HANDLE hThread =  OpenThread(THREAD_ALL_ACCESS,false,threadId);
    NTSTATUS ntstatus =  SystemService::NtTerminateThread(hThread,dwExitCode);
    if (!NT_SUCCESS(ntstatus))
    {
        //结束进程失败,采用驱动方式结束
        qDebug()<<"TerminateThread Fail: ntstatus("<<SystemService::GetFormatNtstatus(ntstatus)<<")";
    }
    SafeCloseHandle(hThread);
    return ntstatus;
}

//枚举进程所有模块
bool ProcessService::EnumProcessModules(DWORD dwPId, QList<ProcessModuleBean> *qProcessModuleList)
{
    DWORD64 dwStartAddr = 0x00000000;
    WCHAR szBuffer[MAX_PATH] = { 0 };
    WCHAR szModuleName[MAX_PATH] = { 0 };
    WCHAR szPathName[MAX_PATH] = { 0 };
    MEMORY_BASIC_INFORMATION mbi;
    PUNICODE_STRING usSectionName;
    BOOL modulex64 = FALSE;
    HANDLE hProcess =  OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwPId);
    if (hProcess == NULL)
    {
        wprintf(L"Open Process %d Error\n", dwPId);
        return false;
    }
    if (NtQueryVirtualMemory)
    {
        do
        {
            if (NtQueryVirtualMemory(
                        hProcess,
                        (PVOID64)dwStartAddr,
                        MemoryBasicInformation,
                        &mbi,
                        sizeof(mbi),
                        0) >= 0)
            {
                if (mbi.Type == MEM_IMAGE)
                {
                    if (NtQueryVirtualMemory(
                                hProcess,
                                (PVOID64)dwStartAddr,
                                MemorySectionName,
                                szBuffer,
                                sizeof(szBuffer),
                                0) >= 0)
                    {
                        usSectionName = (PUNICODE_STRING)szBuffer;

                        if (_wcsnicmp(szModuleName, usSectionName->Buffer, usSectionName->Length / sizeof(WCHAR)))
                        {
                            RtlZeroMemory(szModuleName,MAX_PATH*sizeof(WCHAR));
                            wcsncpy(szModuleName, usSectionName->Buffer, usSectionName->Length / sizeof(WCHAR));
                            NtPathToDosPathW(szModuleName, szPathName);
                            ProcessModuleBean processModuleListBean;
                            processModuleListBean.moduleAddress = (ULONG_PTR)mbi.AllocationBase;
                            processModuleListBean.moduleSize = mbi.RegionSize;
                            processModuleListBean.modulePath = QString::fromWCharArray(szPathName);
                            processModuleListBean.companyName = fileService.GetFileInformation(processModuleListBean.modulePath,CompanyName);
                            ULONG entryPoint=0;
                            if (fileService.GetFileEntryPoint(szPathName,&entryPoint))
                            {
                                //模块入口
                                processModuleListBean.moduleEntryPoint = entryPoint + processModuleListBean.moduleAddress;
                            }
                            qProcessModuleList->append(processModuleListBean);
                            dwStartAddr+=mbi.RegionSize;
                            continue;
                        }
                    }

                }
            }
            dwStartAddr += PAGE_SIZE;
            if (!modulex64) {
                if (dwStartAddr > 0x0000000200000000)
                {
                    modulex64 = TRUE;
                    dwStartAddr = 0x000007fe00000000;
                }
            }
        } while (dwStartAddr < 0x000007ff00000000);
    }
    CloseHandle(hProcess);
    return true;
}






